package com.g.ocache.index.criterion;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;

import com.g.ocache.enums.SortingOrder;


/**
 * 
 * @author Jingqi Xu
 */
public class Criteria {
	
	/**
	 * 
	 */
	public static Criterion basic(Object condition) {
		return new BasicCriterionImpl(condition);
	}
	
	public static Criterion basic(Object... conditions) {
		return new BasicCriterionImpl(Arrays.asList(conditions));
	}
	
	public static Criterion order(SortingOrder order) {
		return new OrderCriterionImpl(order);
	}
	
	public static Criterion from(Object from, boolean isFromInclusive, SortingOrder order) {
		return new RangedCriterionImpl(from, isFromInclusive, null, false, order);
	}
	
	public static Criterion to(Object to, boolean isToInclusive, SortingOrder order) {
		return new RangedCriterionImpl(null, false, to, isToInclusive, order);
	}
	
	public static Criterion ranged(Object from, boolean isFromInclusive, Object to, boolean isToInclusive, SortingOrder order) {
		return new RangedCriterionImpl(from, isFromInclusive, to, isToInclusive, order);
	}
	
	/**
	 * 
	 */
	private static class BasicCriterionImpl implements BasicCriterion {
		//
		private final List<Object> conditions;
		
		/**
		 * 
		 */
		public BasicCriterionImpl(Object condition) {
			this.conditions = new ArrayList<Object>(1);
			this.conditions.add(condition);
		}
		
		public BasicCriterionImpl(List<Object> conditions) {
			this.conditions = new ArrayList<Object>(conditions);
		}
		
		/**
		 * 
		 */
		public String toString() {
			return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
			.append("conditions", conditions).toString();
		}

		/**
		 * 
		 */
		public List<Object> getConditions() {
			return conditions;
		}
	}
	
	private static class OrderCriterionImpl implements OrderCriterion {
		//
		private final SortingOrder order;
		
		/**
		 * 
		 */
		public OrderCriterionImpl(SortingOrder order) {
			this.order = order;
		}
		
		/**
		 * 
		 */
		public String toString() {
			return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
			.append("order", order).toString();
		}
		
		/**
		 * 
		 */
		public SortingOrder getOrder() {
			return order;
		}
	}
	
	private static class RangedCriterionImpl implements RangedCriterion {
		//
		private final Object from;
		private final Object to;
		private final boolean fromInclusive;
		private final boolean toInclusive;
		private final SortingOrder order;
		
		/**
		 * 
		 */
		public RangedCriterionImpl(Object from, boolean fromInclusive, Object to, boolean toInclusive, SortingOrder order) {
			this.from = from;
			this.fromInclusive = fromInclusive;
			this.to = to;
			this.toInclusive = toInclusive;
			this.order = order;
		}
		
		/**
		 * 
		 */
		public String toString() {
			return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
			.append("from", from)
			.append("fromInclusive", fromInclusive)
			.append("to", to)
			.append("toInclusive", toInclusive)
			.append("order", order).toString();
		}
		
		/**
		 * 
		 */
		public Object getFrom() {
			return from;
		}
		
		public Object getTo() {
			return to;
		}
		
		public boolean isFromInclusive() {
			return fromInclusive;
		}
		
		public boolean isToInclusive() {
			return toInclusive;
		}
		
		public SortingOrder getOrder() {
			return order;
		}
	}
}
